package com.sc.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.mybatisflex.core.query.QueryChain;
import com.mybatisflex.spring.service.impl.CacheableServiceImpl;
import com.sc.dto.BeginAttendanceDTO;
import com.sc.entity.AttendanceRecords;
import com.sc.entity.Student;
import com.sc.mapper.AttendanceRecordsMapper;
import com.sc.service.AttendanceRecordsService;
import com.sc.service.ClazzCourseService;
import com.sc.service.CourseService;
import com.sc.service.StudentService;
import com.sc.vo.AttendanceRecordVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import static com.sc.entity.table.AttendanceRecordsTableDef.ATTENDANCE_RECORDS;
import static com.sc.entity.table.StudentTableDef.STUDENT;

/**
 * 考勤记录表 服务层实现。
 *
 * @author JoeZhou
 * @since 2024-09-14
 */
@Service
@CacheConfig(cacheNames = "attendanceRecords")
public class AttendanceRecordsServiceImpl extends CacheableServiceImpl<AttendanceRecordsMapper, AttendanceRecords> implements AttendanceRecordsService {

    @Autowired
    private CourseService courseService;
    @Autowired
    private ClazzCourseService clazzCourseService;
    @Autowired
    private StudentService studentService;
    @Override
    @CacheEvict(allEntries = true)
    public boolean remove(QueryWrapper query) {
        return super.remove(query);
    }

    @Override
    @CacheEvict(allEntries = true)
    public boolean removeById(Serializable id) {
        return super.removeById(id);
    }

    @Override
    @CacheEvict(allEntries = true)
    public boolean removeByIds(Collection<? extends Serializable> ids) {
        return super.removeByIds(ids);
    }

    @Override
    @CacheEvict(allEntries = true)
    public boolean update(AttendanceRecords entity, QueryWrapper query) {
        return super.update(entity, query);
    }

    @Override
    @CacheEvict(allEntries = true)
    public boolean updateById(AttendanceRecords entity, boolean ignoreNulls) {
        return super.updateById(entity, ignoreNulls);
    }

    @Override
    @CacheEvict(allEntries = true)
    public boolean updateBatch(Collection<AttendanceRecords> entities, int batchSize) {
        return super.updateBatch(entities, batchSize);
    }

    @Override
    @Cacheable(key = "#id")
    public AttendanceRecords getById(Serializable id) {
        return super.getById(id);
    }

    @Override
    @Cacheable(key = "#root.methodName + ':' + #query.toSQL()")
    public AttendanceRecords getOne(QueryWrapper query) {
        return super.getOne(query);
    }

    @Override
    @Cacheable(key = "#root.methodName + ':' + #query.toSQL()")
    public <R> R getOneAs(QueryWrapper query, Class<R> asType) {
        return super.getOneAs(query, asType);
    }

    @Override
    @Cacheable(key = "#root.methodName + ':' + #query.toSQL()")
    public Object getObj(QueryWrapper query) {
        return super.getObj(query);
    }

    @Override
    @Cacheable(key = "#root.methodName + ':' + #query.toSQL()")
    public <R> R getObjAs(QueryWrapper query, Class<R> asType) {
        return super.getObjAs(query, asType);
    }

    @Override
    @Cacheable(key = "#root.methodName + ':' + #query.toSQL()")
    public List<Object> objList(QueryWrapper query) {
        return super.objList(query);
    }

    @Override
    @Cacheable(key = "#root.methodName + ':' + #query.toSQL()")
    public <R> List<R> objListAs(QueryWrapper query, Class<R> asType) {
        return super.objListAs(query, asType);
    }

    @Override
    @Cacheable(key = "#root.methodName + ':' + #query.toSQL()")
    public List<AttendanceRecords> list(QueryWrapper query) {
        return super.list(query);
    }

    @Override
    public Page<AttendanceRecordVo> list(Page page, Long scheduleId) {
        Page<AttendanceRecordVo> attendanceRecordVos = QueryChain.of(mapper)
                .select(ATTENDANCE_RECORDS.DEFAULT_COLUMNS, STUDENT.NAME, STUDENT.CLAZZ_NAME)
                .from(ATTENDANCE_RECORDS)
                .leftJoin(STUDENT).on(ATTENDANCE_RECORDS.STUDENT_ID.eq(STUDENT.ID))
                .where(ATTENDANCE_RECORDS.TEACHING_SCHEDULE_ID.eq(scheduleId))
                .pageAs(page, AttendanceRecordVo.class);
//                .listAs(AttendanceRecordVo.class);
        return attendanceRecordVos;
    }
    @Override
    @Cacheable(key = "#root.methodName + ':' + #query.toSQL()")
    public <R> List<R> listAs(QueryWrapper query, Class<R> asType) {
        return super.listAs(query, asType);
    }

    /**
     * @deprecated 无法通过注解进行缓存操作。
     */
    @Override
    @Deprecated
    public List<AttendanceRecords> listByIds(Collection<? extends Serializable> ids) {
        return super.listByIds(ids);
    }

    @Override
    @Cacheable(key = "#root.methodName + ':' + #query.toSQL()")
    public long count(QueryWrapper query) {
        return super.count(query);
    }

    @Override
    @Cacheable(key = "#root.methodName + ':' + #page.getPageSize() + ':' + #page.getPageNumber() + ':' + #query.toSQL()")
    public <R> Page<R> pageAs(Page<R> page, QueryWrapper query, Class<R> asType) {
        return mapper.paginateWithRelationsAs(page.getPageNumber(),page.getPageSize(),query,asType);
    }

    @Override
    @CacheEvict(allEntries = true)
    public boolean save(AttendanceRecords entity) {
        return super.save(entity);
    }


    @Override
    @Transactional
    public boolean beginAttendance(BeginAttendanceDTO dto) {
        // 查询本次排课的考勤记录状态，如果是考勤记录数大于0，说明已经初始化考勤了
        QueryWrapper queryWrapper = QueryWrapper.create().eq("teaching_schedule_id", dto.getScheduleId());
        if (this.count(queryWrapper) > 0)
            return true;
        // 先查询这门课考勤是否有年级限制
        queryWrapper.clear();
        queryWrapper.select("map_grade_list").eq("id", dto.getCourseId());
        String mapGradeList = courseService.getOneAs(queryWrapper, String.class);
        List<Long> gradeList = new ArrayList<>();
        // 如果考勤有年级限制，找出哪些年级学生需要考勤
        if (!mapGradeList.equalsIgnoreCase("ALL")) {
            String[] tempArr = mapGradeList.split(",");
            for (String s : tempArr) {
                gradeList.add(Long.valueOf(s));
            }
        }
        // 查询需要考勤的班级
        queryWrapper.clear();
        queryWrapper.select("clazz_id").eq("course_id", dto.getCourseId());
        List<Long> clazzIds = clazzCourseService.listAs(queryWrapper, Long.class);
        // 再查询需要考勤的学生
        queryWrapper.clear();
        queryWrapper.in("clazz_id", clazzIds);
        // 如果有年级限制，增加这个条件
        if (CollUtil.isNotEmpty(gradeList)) {
            queryWrapper.in("grade_id", gradeList);
        }
        queryWrapper.select("id", "clazz_id");
        List<Student> studentList = studentService.list(queryWrapper);
        List<AttendanceRecords> recordsList = new ArrayList(studentList.size());
        for (Student student : studentList) {
            AttendanceRecords record = new AttendanceRecords();
            record.setTeachingScheduleId(dto.getScheduleId());
            record.setStudentId(student.getId());
            record.setClazzId(student.getClazzId());
            record.setStatus(1);//默认都出勤
            recordsList.add(record);
        }
        return this.saveBatch(recordsList);
    }

    @Override
    @CacheEvict(allEntries = true)
    @Transactional
    public boolean updateBatch(Collection<AttendanceRecords> entities) {
        entities.forEach(record -> {
            this.updateById(record, true);
        });
        return true;
    }
}
